using System;
using System.Collections;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace WindowsAPI
{
    /// <summary>Shows default file icon</summary>
    public class IconHandler
    {
        //struct ShellFileInformation 
        private static Hashtable ExtentionList = new Hashtable();
        private static Hashtable ExtentionTypeList = new Hashtable();
        public static ImageList LargeImageList;
        //private struct SHFILEINFO
        //{
        //    public IntPtr hIcon;
        //    public IntPtr iIcon;
        //    public uint dwAttributes;
        //    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        //    public string szDisplayName;
        //    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
        //    public string szTypeName;
        //};

        //icon consts
        //private const uint SHGFI_ICON = 0x100;
        //private const uint SHGFI_LARGEICON = 0x0;    // 'Large icon (32X32)
        //private const uint SHGFI_USEFILEATTRIBUTES = 0x10; //No Real Disk Access (see url below)
        //public const uint SHGFI_TYPENAME = 0x400;     // get type name
        //public const uint FILE_ATTRIBUTE_NORMAL = 0x80;


        ///// <summary>
        ///// Retrieves information about an object in the file system, such as a file, a folder, a directory, or a drive root.
        ///// (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/functions/shgetfileinfo.asp)
        ///// </summary>
        //[DllImport("shell32.dll")]
        //private static extern IntPtr SHGetFileInfo(
        //    string pszPath,				//path
        //    uint dwFileAttributes,		//attributes
        //    ref SHFILEINFO psfi,		//struct pointer
        //    uint cbSizeFileInfo,		//size
        //    uint uFlags);				//flags

        //[DllImport("User32.dll")]
        //public static extern int DestroyIcon(IntPtr hIcon);

        /// <summary>Gets the Icon from Shell by using the extention</summary>
        /// <param name="Extention"></param>
        /// <returns></returns>
        public static int GetIcon(string Extention)
        {
            try
            {
                if(ExtentionList.Contains(Extention))
                    return (int)ExtentionList[Extention];
                var pos = LargeImageList.Images.Count;		//store current count -- new item's index

                LargeImageList.Images.Add(GetIconFromShell(Extention));	//add to image list


                ExtentionList.Add(Extention, pos);	// add to hash table

                return pos;
            }
            catch(Exception)
            {
                //Console.WriteLine(ex.Message);
                return 0;
            }
        }

        /// <summary>Retrieves information on the extension of a file and shows its Icon</summary>
        /// <param name="Extention">File extension</param>
        /// <returns>Mathing Icon</returns>
        private static Icon GetIconFromShell(string Extention)
        {
            try
            {
                //add '.' if nessesry
                if(Extention[0] != '.') Extention = '.' + Extention;

                //struct for getting file shell info
                var shinfo = new SHFILEINFO();

                //get Shell File Info			
                Shell32.SHGetFileInfo(
                    Extention,
                    eFileAttributes.Normal,
                    ref shinfo,
                    (uint)Marshal.SizeOf(shinfo),
                    SHGFI.Icon | SHGFI.UseFileAttributes | SHGFI.LargeIcon);


                var icon = (Icon)Icon.FromHandle(shinfo.hIcon).Clone();
                User32.DestroyIcon(shinfo.hIcon);		// Cleanup

                return icon;

            }
            catch(Exception e)
            {

                Debug.WriteLine("Error while trying to get icon for " + Extention + " :" + e.Message);
                return null;
            }

        }

        /// <summary>Retrieves information on the extension of a file and shows its Icon</summary>
        /// <param name="Extention">File extension</param>
        /// <returns>Mathing Icon</returns>
        public static string GetIconTypeFromShell(string Extention)
        {
            try
            {
                //add '.' if nessesry
                if(Extention[0] != '.') Extention = '.' + Extention;

                if(ExtentionTypeList.Contains(Extention))
                    return (string)ExtentionTypeList[Extention];
                //struct for getting file shell info
                var shinfo = new SHFILEINFO();

                //get Shell File Info			
                Shell32.SHGetFileInfo(
                    Extention,
                    eFileAttributes.Normal,
                    ref shinfo,
                    (uint)Marshal.SizeOf(shinfo),
                    SHGFI.UseFileAttributes | SHGFI.TypeName);



                ExtentionTypeList.Add(Extention, shinfo.szTypeName);
                return shinfo.szTypeName;
            }
            catch(Exception e)
            {
                Debug.WriteLine("Error while trying to get icon type for " + Extention + " :" + e.Message);
                return "";
            }

        }

    }
}